package com.yunsc.order.sevice.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yunsc.common.exception.YunscException;
import com.yunsc.order.dto.CheckoutOrderDTO;
import com.yunsc.order.entity.YunscOrderEntity;
import com.yunsc.order.handler.impl.RedisDelayQueueEnum;
import com.yunsc.order.sevice.CheckoutOrderService;
import com.yunsc.order.sevice.YunscOrderAddressService;
import com.yunsc.order.sevice.YunscOrderGoodsService;
import com.yunsc.order.sevice.YunscOrderService;
import com.yunsc.order.utils.RedisDelayQueueUtil;
import com.yunsc.order.vo.CheckOrderGoodsVO;
import com.yunsc.order.vo.CheckOrderVO;
import com.yunsc.order.vo.CheckoutOrderVO;
import com.yunsc.order.vo.PersonalVO;
import com.yunsc.product.service.YunscGoodsService;
import com.yunsc.product.vo.GoodsInfoVO;
import com.yunsc.store.entity.*;
import com.yunsc.store.service.*;
import com.yunsc.store.vo.OrderSettingVO;
import com.yunsc.store.vo.PointConfigVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @version: 1.0
 * @Author: adan
 * @description: 订单结算服务实现类
 * @date: 2024-05-12 14:04
 */
@Slf4j
@Service
public class CheckoutOrderServiceImpl implements CheckoutOrderService {

    @Resource
    private YunscUserService userService;
    @Resource
    private YunscUserAddressService userAddressService;
    @Resource
    private YunscStoreSettingService storeSettingService;
    @Resource
    private YunscCartService cartService;
    @Resource
    private YunscGoodsService goodsService;
    @Resource
    private YunscDeliveryService deliveryService;
    @Resource
    private YunscUserCouponService userCouponService;
    @Resource
    private YunscOrderService orderService;
    @Resource
    private YunscOrderGoodsService orderGoodsService;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private CheckoutOrderService checkoutOrderService;
    @Resource
    private YunscOrderAddressService orderAddressService;
    @Resource
    private RedisDelayQueueUtil redisDelayQueueUtil;

    @Override
    public CheckoutOrderVO checkoutOrder(CheckoutOrderDTO params, Integer userId, Integer storeId) {
        List<YunscCartEntity> goodsCarts = getCheckoutOrderGoodsCarts(params);

        // 用户信息
        YunscUserEntity user = userService.queryUserInfo(userId);
        // 用户默认收货地址
        YunscUserAddressEntity userAddress = userAddressService.queryUserAddressDetail(user.getAddressId());

        // 系统是否开启积分抵扣
        String pointData = storeSettingService.queryPointData(storeId); // 积分抵扣规则
        PointConfigVO pointConfig = JSON.parseObject(pointData, PointConfigVO.class);

        // 错误信息
        boolean hasError = false;
        String errorMsg = "";

        // 获取商品列表
        List<CheckOrderGoodsVO> checkOrderGoodsList = new ArrayList<>();
        // 订单商品总数
        int orderTotalNum = 0;
        // 订单总价
        BigDecimal orderTotalPrice = BigDecimal.ZERO;

        List<Integer> goodsIds = new ArrayList<>();
        for (YunscCartEntity goodsCart : goodsCarts) {
            Integer goodsNum = goodsCart.getGoodsNum();
            // 累加订单商品总数
            orderTotalNum += goodsNum;
            Integer goodsId = goodsCart.getGoodsId();
            goodsIds.add(goodsId);
            String goodsSkuId = goodsCart.getGoodsSkuId();
            CheckOrderGoodsVO orderGoods = new CheckOrderGoodsVO();     // 商品信息
            GoodsInfoVO goodsInfoVO = goodsService.queryGoodsInfo(goodsId, goodsSkuId);
            BeanUtils.copyProperties(goodsInfoVO, orderGoods);
            orderGoods.setGoodsPrice(goodsInfoVO.getSkuInfo().getGoodsPrice());
            orderGoods.setGoodsSkuId(goodsSkuId);
            orderGoods.setTotalNum(goodsNum);
            // 设置商品会员折扣
            String goodsPrice = orderGoods.getSkuInfo().getGoodsPrice(); // 商品原价
            int isEnableGrade = orderGoods.getIsEnableGrade(); // 是否启用会员折扣
            BigDecimal goodsPayPrice = BigDecimal.ZERO;
            if (isEnableGrade == 1 && user.getGrade().getEquity() != null) {
                orderGoods.setIsUserGrade(true);
                // 会员
                //  getMemberPrice(user.getGrade(), goodsNum, orderGoods, goodsPrice);
                // 计算会员折扣
                // 会员价格
                String equity = user.getGrade().getEquity();
                Map map = JSON.parseObject(equity, Map.class);
                String gradeRatio = (String) map.get("discount");   // 9.7折
                // 会员折扣价格（原价*97%=现价）
                BigDecimal gradePriceGoods = new BigDecimal(goodsPrice).multiply(new BigDecimal(gradeRatio)).multiply(new BigDecimal("0.1"))
                        .setScale(2, RoundingMode.HALF_UP);
                // 会员优惠的金额（商品原价 - 会员价格）
                BigDecimal gradeTotalPrice = new BigDecimal(goodsPrice).subtract(gradePriceGoods);
                goodsPayPrice = gradePriceGoods.multiply(BigDecimal.valueOf(goodsNum)).setScale(2, RoundingMode.HALF_UP);
                // 设置会员折扣信息
                orderGoods.setGradeRatio(gradeRatio);
                orderGoods.setGradeGoodsPrice(String.valueOf(gradePriceGoods));
                orderGoods.setGradeTotalMoney(String.valueOf(gradeTotalPrice));
            } else {
                // 商品总价
                goodsPayPrice = new BigDecimal(goodsPrice).multiply(BigDecimal.valueOf(goodsNum)).setScale(2, RoundingMode.HALF_UP);
                // 普通用户
                orderGoods.setGradeRatio("0");
                orderGoods.setGradeGoodsPrice("0.00");
                orderGoods.setGradeTotalMoney("0.00");
            }
            orderGoods.setTotalPrice(String.valueOf(goodsPayPrice));
            orderGoods.setTotalPayPrice(String.valueOf(goodsPayPrice));
            // 累加商品总价
            orderTotalPrice = orderTotalPrice.add(goodsPayPrice);

            // 设置商品运费 expressPrice
            YunscDeliveryRuleEntity deliveryRule = deliveryService.queryDeliveryBigDecimalById(orderGoods.getDeliveryId());
            // 判断是否在配送区域内 isIntraRegion;
            if (userAddress != null) {
                String region = deliveryRule.getRegion();
                boolean intraRegion = isIntraRegion(region, userAddress.getCityId());
                if (intraRegion) {
                    // 计算运费
                    String expressPrice = getGoodsExpressPrice(orderGoods, goodsNum, deliveryRule);
                    orderGoods.setExpressPrice(expressPrice);
                }
                orderGoods.setIsIntraRegion(intraRegion);
            }
            // 判断错误信息
            // 判断是否限购
            // 判断商品是否开启限购(0未开启 1已开启)
            int isRestrict = orderGoods.getIsRestrict();
            if (isRestrict == 1) {
                // 商品限购
                // 总限购数量(0为不限制)
                int restrictTotal = orderGoods.getRestrictTotal();
                if (restrictTotal > 0) {
                    // 总限购数量，查询用户购买过的商品数量
                    int totalNum = orderGoodsService.queryUserOrderGoodsNum(goodsId, userId);
                    if (totalNum >= restrictTotal) {
                        hasError = true;
                        errorMsg = "商品限购数量已满";
                        break;
                    }
                }
                // 每单限购数量(0为不限制)
                int restrictSingle = orderGoods.getRestrictSingle();
                if (restrictSingle > 0) {
                    // 每单限购数量
                    int singleNum = orderGoods.getTotalNum();
                    if (singleNum >= restrictSingle) {
                        hasError = true;
                        errorMsg = "商品每单限购数量已满";
                        break;
                    }
                }
            }
            // 判断库存
            if (goodsInfoVO.getSkuInfo().getStockNum() < goodsNum) {
                hasError = true;
                errorMsg = "商品库存不足";
                break;
            }
            // 判断商品是否在配送区域
            if (!orderGoods.getIsIntraRegion()) {
                hasError = true;
                errorMsg = "商品[" + goodsInfoVO.getGoodsName() + "]不在配送区域";
                break;
            }

            // 添加商品信息到列表
            checkOrderGoodsList.add(orderGoods);
        }

        // 用户优惠券
        List<YunscUserCouponEntity> couponList = userCouponService.queryGoodsAvailableCoupons(params.getCouponId(), userId, orderTotalPrice, goodsIds);

        // 构建订单信息
        CheckOrderVO orderVO = buildCheckOrderVO(params, user, userAddress, hasError, errorMsg, checkOrderGoodsList,
                orderTotalNum, orderTotalPrice, couponList,storeId);

        // CheckOrderVO orderVO = buidCheckOrderVO(params, userAddress, couponList, hasError, errorMsg, checkOrderGoodsList, user);
        // 构建订单优惠信息
        CheckOrderVO orderDiscount = buildOrderDiscount(
                pointConfig, checkOrderGoodsList, orderTotalPrice, couponList, orderVO, userAddress.getCityId(), storeId);

        // 构建返回结果
        CheckoutOrderVO checkoutOrderVO = buildCheckoutOrderVO(userId, storeId, user, pointConfig, orderDiscount);

        return checkoutOrderVO;
    }

    private List<YunscCartEntity> getCheckoutOrderGoodsCarts(CheckoutOrderDTO params) {
        List<YunscCartEntity> goodsCarts = new ArrayList<>();
        if ("cart".equals(params.getMode())) {
            // 获取购物车id
            String cartIds = params.getCartIds();
            // 根据cartIds获取商品信息
            goodsCarts = queryGoodsByCartIds(cartIds);
        } else {
            // 直接购买
            String goodsId = params.getGoodsId();
            String goodsSkuId = params.getGoodsSkuId();
            String goodsNum = params.getGoodsNum();
            YunscCartEntity carts = new YunscCartEntity();
            carts.setGoodsId(Integer.valueOf(goodsId));
            carts.setGoodsSkuId(goodsSkuId);
            carts.setGoodsNum(Integer.valueOf(goodsNum));
            goodsCarts.add(carts);
        }
        return goodsCarts;
    }

    @Override
    public Integer checkoutOrderSubmit(CheckoutOrderDTO params, Integer userId, Integer storeId, String platform) {
        // 1、获取订单信息
        CheckoutOrderVO orderVO = checkoutOrder(params, userId, storeId);
        CheckOrderVO order = orderVO.getOrder();
        order.setBuyerRemark(params.getRemark());
        // 2、验库存（）
        if (order.getHasError()) {
            throw new YunscException(order.getErrorMsg());
        }

        // 3、验余额、积分
        PersonalVO personal = orderVO.getPersonal();
        // if (personal == null || new BigDecimal(personal.getBalance()).compareTo(new BigDecimal(order.getOrderPayPrice())) < 0) {
        //     throw new YunscException("余额不足");
        // }
        Integer isUsePoints = params.getIsUsePoints();
        if (isUsePoints != null && isUsePoints == 1 && new BigDecimal(personal.getPoints()).compareTo(new BigDecimal(order.getPointsNum())) < 0) {
            throw new YunscException("积分不足");
        }

        // 4. 获取Redisson的分布式锁实例
        RLock lock = redissonClient.getLock("lock:order:" + userId);
        // 获取锁对象
        boolean isLock = lock.tryLock();
        // 加锁失败
        if (!isLock) {
            log.error("获取锁失败");
            throw new YunscException("不允许重复下单");
        }
        try {
            // 生成订单
            YunscOrderEntity orderEntity = checkoutOrderService.createOrder(userId, params, order, storeId, platform);
            // 获取商品库存计算方式，判断是下单减库存还是付款后减库存
            order.getGoodsList().forEach(goods -> {
                // 库存计算方式(10下单减库存 20付款减库存)
                if (goods.getDeductStockType() == 10) {
                    // 减库存
                    goodsService.deductStock(goods.getGoodsId(), goods.getGoodsSkuId(), goods.getTotalNum());
                }
            });
            // 扣除用户积分
            if (order.getIsUsePoints() == 1 && order.getPointsNum() > 0) {
                userService.subtractPoints(userId, order.getPointsNum(), "下单使用积分抵扣");
            }

            if ("cart".equals(params.getMode()) && StringUtils.isNotEmpty(params.getCartIds())) {
                // 获取购物车id
                List<Integer> cartIds = getCartIdsByCartId(params.getCartIds());
                // 购物车商品删除
                cartService.clearUserCart(userId, cartIds);
            }

            // 添加redission延迟队列，订单支付超时，自动取消订单延迟队列
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", orderEntity.getOrderId());
            map.put("remark", "订单支付超时，自动取消订单");
            // 获取系统配置的超时时间
            OrderSettingVO orderSettingVO = storeSettingService.queryOrderSettingVO(storeId);
            int closeHours = orderSettingVO.getOrder().getCloseHours(); // 订单关闭时间（小时）
            if (closeHours == 0){
                // 关闭订单时间为0，不添加延迟队列
                return orderEntity.getOrderId();
            }
            // 超时时间（秒）
            int timeoutSeconds = closeHours * 60 * 60;
            // 添加订单支付超时，自动取消订单延迟队列。
            redisDelayQueueUtil.addDelayQueue(map, timeoutSeconds, TimeUnit.SECONDS, RedisDelayQueueEnum.ORDER_PAYMENT_TIMEOUT.getCode());
            log.info("订单支付超时，自动取消订单延迟队列添加成功，消息内容：{}", map);
            return orderEntity.getOrderId();
        } finally {
            // 释放锁
            lock.unlock();
        }

    }

    @Transactional
    @Override
    public YunscOrderEntity createOrder(Integer userId, CheckoutOrderDTO param, CheckOrderVO order, Integer storeId, String platform) {
        // 生成订单
        // 3、生成订单
        YunscOrderEntity orderEntity = orderService.saveOrderDb(userId, param.getRemark(), order, platform);
        // 4、订单商品表
        List<CheckOrderGoodsVO> goodsList = order.getGoodsList();
        orderGoodsService.saveOrderGoodsDb(userId, orderEntity, goodsList,storeId);
        // 5、订单地址表
        YunscUserAddressEntity address = order.getAddress();
        orderAddressService.saveOrderAddressDB(address, userId, orderEntity.getOrderId(), storeId);
        return orderEntity;
    }


    @NotNull
    private CheckoutOrderVO buildCheckoutOrderVO(Integer userId, Integer storeId, YunscUserEntity user, PointConfigVO pointConfig, CheckOrderVO orderVO) {
        PersonalVO personalVO = new PersonalVO();
        personalVO.setUserId(userId);
        personalVO.setPoints(user.getPoints());
        personalVO.setBalance(user.getBalance());
        personalVO.setAddressId(user.getAddressId());

        List<Integer> deliveryType = storeSettingService.queryStoreDelivery(storeId);
        CheckoutOrderVO.SettingVO settingVO = new CheckoutOrderVO.SettingVO();
        settingVO.setDeliveryType(deliveryType);
        settingVO.setPointsName(pointConfig.getPointsName());
        settingVO.setPointsDescribe(pointConfig.getDescribe());

        CheckoutOrderVO checkoutOrderVO = new CheckoutOrderVO();
        checkoutOrderVO.setOrder(orderVO);
        checkoutOrderVO.setSetting(settingVO);
        checkoutOrderVO.setPersonal(personalVO);
        return checkoutOrderVO;
    }

    /**
     * 构建订单信息
     *
     * @param params              参数
     * @param user                用户
     * @param userAddress         用户地址
     * @param hasError            是否有错误
     * @param errorMsg            错误信息
     * @param checkOrderGoodsList 商品信息
     * @param orderTotalNum       订单总数量
     * @param orderTotalPrice     订单总价格
     * @param couponList          优惠券列表
     * @return CheckOrderVO
     */
    private CheckOrderVO buildCheckOrderVO(
            CheckoutOrderDTO params, YunscUserEntity user, YunscUserAddressEntity userAddress,
            boolean hasError, String errorMsg, List<CheckOrderGoodsVO> checkOrderGoodsList,
            int orderTotalNum, BigDecimal orderTotalPrice,
            List<YunscUserCouponEntity> couponList,
            Integer storeId
    ) {
        CheckOrderVO orderVO = new CheckOrderVO();
        orderVO.setGoodsList(checkOrderGoodsList);
        orderVO.setOrderTotalNum(orderTotalNum);
        orderVO.setCouponList(couponList);
        orderVO.setHasError(hasError);
        orderVO.setErrorMsg(errorMsg);
        orderVO.setOrderType(10);
        orderVO.setDelivery(10);
        orderVO.setExistAddress(userAddress != null);
        orderVO.setAddress(userAddress);
        String expressPrice = calculateShippingFee(checkOrderGoodsList);
        orderVO.setExpressPrice(expressPrice);
        boolean isIntraRegion = checkOrderGoodsList.stream().anyMatch(CheckOrderGoodsVO::getIsIntraRegion);
        orderVO.setIsIntraRegion(isIntraRegion);
        orderVO.setIsAllowPoints(false);
        orderVO.setIsUsePoints(params.getIsUsePoints());
        orderVO.setPointsNum(user.getPoints());
        orderVO.setOrderTotalPrice(String.valueOf(orderTotalPrice));
        orderVO.setCouponId(params.getCouponId());
        orderVO.setOrderPrice(String.valueOf(orderTotalPrice));
        String orderPayPrice = orderTotalPrice.add(new BigDecimal(expressPrice)).toString();
        orderVO.setOrderPayPrice(orderPayPrice);
        orderVO.setStoreId(storeId);
        return orderVO;
    }

    private CheckOrderVO buildOrderDiscount(
            PointConfigVO pointConfig,
            List<CheckOrderGoodsVO> checkOrderGoodsList,
            BigDecimal orderTotalPrice,
            List<YunscUserCouponEntity> couponList,
            CheckOrderVO orderVO,
            Integer cityId,
            Integer storeId
    ) {
        // 1.开启积分抵扣条件（1.用户积分是否大于0；2.系统是否开启积分抵扣；3.订单金额是否大于最低订单金额）
        // 系统是否开启积分抵扣
        int isShoppingDiscount = pointConfig.getIsShoppingDiscount();
        // 最低订单金额
        PointConfigVO.PointsDiscountVO discount = pointConfig.getDiscount();
        String fullOrderPrice = discount.getFullOrderPrice();
        Integer userPoints = orderVO.getPointsNum();
        // 积分抵扣金额
        BigDecimal pointDiscount = BigDecimal.ZERO;
        if (isShoppingDiscount == 1 && userPoints > 0 && orderTotalPrice.compareTo(new BigDecimal(fullOrderPrice)) >= 0) {
            // 计算积分抵扣金额
            // 总共积分抵扣的金额
            pointDiscount = getPointsDeductionPrice(discount.getDiscountRatio(), discount.getMaxMoneyRatio(), orderTotalPrice, userPoints);
            // 积分抵扣金额
            orderVO.setIsAllowPoints(true);
        }


        // 2.是否使用优惠券
        // 使用的优惠券id
        Integer userCouponId = orderVO.getCouponId();
        // 优惠券抵扣金额
        BigDecimal couponAmount = BigDecimal.ZERO;
        if (userCouponId != null && userCouponId > 0) {
            couponAmount = getCouponMoney(couponList, orderTotalPrice, userCouponId);
        }


        // 计算开启积分抵扣后的商品总价格
        double goodsPointsTotalPrice = checkOrderGoodsList.stream().filter(goods -> goods.getIsPointsDiscount() == 1)
                .mapToDouble(goods -> Double.parseDouble(goods.getTotalPrice())).sum();
        BigDecimal goodsPointsTotalPriceBigDecimal = new BigDecimal(goodsPointsTotalPrice);

        // 积分奖励
        int totalPointsBonus = 0;

        // 按比例计算每个商品抵扣的积分、金额
        for (CheckOrderGoodsVO goods : checkOrderGoodsList) {
            BigDecimal goodsTotalPrice = new BigDecimal(goods.getTotalPrice());
            // 积分抵扣金额
            BigDecimal pointDiscountAmount = BigDecimal.ZERO;
            // 是否允许使用积分抵扣(1允许 0不允许)
            if (goods.getIsPointsDiscount() == 1) {
                BigDecimal ratio = goodsTotalPrice.divide(goodsPointsTotalPriceBigDecimal, 10, BigDecimal.ROUND_HALF_UP);
                // 计算商品抵扣的积分、金额
                if (pointDiscount.compareTo(BigDecimal.ZERO) > 0) {
                    pointDiscountAmount = ratio.multiply(pointDiscount).setScale(2, RoundingMode.HALF_UP);
                }
            }

            // 优惠券抵扣金额
            BigDecimal ratio = goodsTotalPrice.divide(orderTotalPrice, 10, BigDecimal.ROUND_HALF_UP);
            BigDecimal couponDiscountAmount = BigDecimal.ZERO;
            if (couponAmount != null && couponAmount.compareTo(BigDecimal.ZERO) > 0) {
                couponDiscountAmount = ratio.multiply(couponAmount).setScale(2, RoundingMode.HALF_UP);
            }

            // 系统是否开启满额包邮
            boolean isFreePostage = storeSettingService.queryIsFreePostage(storeId, cityId, orderTotalPrice);
            // 计算商品运费
            if (!isFreePostage) {
                // 计算商品运费
                BigDecimal expressPrice = new BigDecimal(goods.getExpressPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
                orderTotalPrice = orderTotalPrice.add(expressPrice);
            } else {
                // 免邮
                goods.setExpressPrice("0.00");
            }


            // 计算商品抵扣后的价格
            BigDecimal discountedPrice = goodsTotalPrice.subtract(pointDiscountAmount).subtract(couponDiscountAmount);

            // 设置积分奖励，
            // 商品是否开启积分赠送(1开启 0关闭) 、 系统是否开启积分赠送
            int pointsBonus = 0;
            if (goods.getIsPointsGift() == 1 && pointConfig.getIsShoppingGift() == 1) {
                // 获取积分奖励比例
                String giftRatio = pointConfig.getGiftRatio();
                // 计算积分奖励
                // 创建一个表示10%的BigDecimal对象，这里需要指定精度，因为0.1无法精确表示为二进制小数
                // 将值除以100
                BigDecimal value = new BigDecimal(giftRatio);
                BigDecimal maxGiftRadio = value.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                // 最大赠送积分数量
                BigDecimal pointsMoneyNum = discountedPrice.multiply(maxGiftRadio).setScale(2, RoundingMode.HALF_UP);
                // 计算最大赠送积分数量
                // BigDecimal maxPointsBonusDecimal = goodsTotalPrice.multiply(maxGiftRadio).setScale(2, RoundingMode.HALF_UP);
                pointsBonus = pointsMoneyNum.toBigInteger().intValue();
                // 总共积分奖励
                totalPointsBonus += pointsBonus;
            }


            // 输出结果
            // System.out.println("商品原价：" + goodsTotalPrice +
            //         "，积分抵扣金额：" + pointDiscountAmount +
            //         "，优惠券抵扣金额：" + couponDiscountAmount +
            //         "，抵扣后价格：" + discountedPrice +
            //         "，积分奖励：" + pointsBonus);
            goods.setPointsMoney(pointDiscountAmount.toPlainString());
            goods.setCouponMoney(couponDiscountAmount.toPlainString());
            goods.setPointsBonus(pointsBonus);
            goods.setTotalPayPrice(discountedPrice.toPlainString());
        }

        // 是否使用积分抵扣
        if (orderVO.getIsUsePoints() == 1) {
            orderTotalPrice = orderTotalPrice.subtract(pointDiscount);
            // orderVO.setPointsMoney(String.valueOf(pointDiscount));
        }
        orderVO.setPointsMoney(String.valueOf(pointDiscount));

        // 是否使用优惠券
        if (userCouponId != null && userCouponId > 0) {
            orderTotalPrice = orderTotalPrice.subtract(couponAmount);
            orderVO.setCouponMoney(String.valueOf(couponAmount));
            orderVO.setCouponId(userCouponId);
        }

        orderVO.setPointsBonus(totalPointsBonus);
        orderVO.setOrderPayPrice(String.valueOf(orderTotalPrice));
        orderVO.setOrderPrice(String.valueOf(orderTotalPrice));

        return orderVO;
    }

    /**
     * 计算运费
     *
     * @param productList 商品列表
     * @return 运费
     */
    public String calculateShippingFee(List<CheckOrderGoodsVO> productList) {
        if (productList.isEmpty()) {
            return "0.00"; // 如果商品列表为空，则总的运费为0
        }

        if (productList.stream().anyMatch(product -> product.getExpressPrice().equals("0.00"))) {
            return "0.00"; // 如果有任何一个商品的运费为0，则总的运费为0
        }

        double totalFee = productList.stream()
                .mapToDouble(product -> Double.parseDouble(product.getExpressPrice()))
                .sum();

        return String.valueOf(totalFee);
    }


    /**
     * 获取优惠券金额
     *
     * @param userCouponList  用户优惠券列表
     * @param orderTotalPrice 商品总价
     * @param userCouponId    优��券id
     * @return BigDecimal 优惠券金额
     */
    private static BigDecimal getCouponMoney(List<YunscUserCouponEntity> userCouponList, BigDecimal orderTotalPrice, Integer userCouponId) {
        if (userCouponList.isEmpty()) {
            // 如果用户优惠券列表为空，根据业务需求返回默认值或抛出异常
            return BigDecimal.ZERO; // 或者根据业务需求抛出异常
        }

        Optional<YunscUserCouponEntity> optionalCoupon = userCouponList.stream()
                .filter(coupon -> coupon.getUserCouponId().equals(userCouponId))
                .findFirst();

        BigDecimal couponMoney = optionalCoupon.map(coupon -> {
            if (!coupon.getIsApply()) {
                throw new YunscException("该优惠券不可用");
            }
            Integer couponType = coupon.getCouponType();
            switch (couponType) {
                case 10: // 满减券处理
                    BigDecimal minPrice = new BigDecimal(coupon.getMinPrice());
                    if (minPrice.compareTo(BigDecimal.ZERO) <= 0) {
                        throw new YunscException("满减条件必须大于零");
                    }
                    if (orderTotalPrice.compareTo(minPrice) >= 0) {
                        // 符合满减条件，判断减免金额是否大于商品金额
                        BigDecimal reducePrice = new BigDecimal(coupon.getReducePrice());
                        if (reducePrice.compareTo(orderTotalPrice) > 0) {
                            return orderTotalPrice;
                        } else {
                            return reducePrice;
                        }
                    }
                    return BigDecimal.ZERO;
                case 20: // 折扣券处理
                    BigDecimal discount = new BigDecimal(coupon.getDiscount());
                    if (discount.compareTo(BigDecimal.ZERO) <= 0 || discount.compareTo(BigDecimal.valueOf(100)) > 0) {
                        throw new YunscException("折扣比例必须大于零且小于等于100");
                    }
                    // 折扣金额 = 商品金额 * 折扣比例 / 100
                    BigDecimal discountedAmount = orderTotalPrice.multiply(discount.divide(BigDecimal.valueOf(100))).setScale(2, RoundingMode.HALF_UP);
                    // 判断折扣金额是否大于商品金额
                    if (discountedAmount.compareTo(orderTotalPrice) > 0) {
                        return orderTotalPrice;
                    }
                    return discountedAmount;
                default:
                    return BigDecimal.ZERO;
            }
        }).orElse(BigDecimal.ZERO);
        return couponMoney;
    }


    /**
     * 获取商品运费
     *
     * @param goods        商品信息
     * @param goodsNum     商品数量
     * @param deliveryRule 配送规则
     * @return String 运费
     */
    private static String getGoodsExpressPrice(CheckOrderGoodsVO goods, Integer goodsNum, YunscDeliveryRuleEntity deliveryRule) {
        Integer method = deliveryRule.getMethod();
        BigDecimal totalFee = BigDecimal.ZERO;

        Double goodsWeight = goods.getSkuInfo().getGoodsWeight();
        // 首件(个)/首重(Kg)
        Double first = deliveryRule.getFirst();
        // 首件(个)/首重(Kg) 价格
        BigDecimal firstFee = new BigDecimal(deliveryRule.getFirstFee());
        // 续件/续重
        Double additional = deliveryRule.getAdditional();
        // 续件/续重(价格)
        BigDecimal additionalFee = new BigDecimal(deliveryRule.getAdditionalFee());
        // 如果价格都为0，则不计算运费
        if (firstFee.compareTo(BigDecimal.ZERO) == 0 && additionalFee.compareTo(BigDecimal.ZERO) == 0) {
            return "0.00";
        }
        if (method == 10) {
            // 10按件数
            totalFee = firstFee.add(additionalFee.multiply(new BigDecimal(goodsNum - 1)));
        } else if (method == 20) {
            // 20按重量
            // 续重价格
            if (goodsWeight <= first) {
                totalFee = firstFee;
            } else {
                BigDecimal additionalWeightFee = BigDecimal.valueOf(Math.ceil((goodsWeight - first) / additional)).multiply(additionalFee);
                totalFee = firstFee.add(additionalWeightFee);
            }
        }
        return String.valueOf(totalFee);
    }

    /**
     * 判断是否在配送区域内
     *
     * @param region   可配送区域(城市id集)
     * @param regionId 地址id
     * @return
     */
    private boolean isIntraRegion(String region, Integer regionId) {
        ObjectMapper mapper = new ObjectMapper(); // 创建一个ObjectMapper对象
        List<Integer> regionIds = null;
        try {
            regionIds = mapper.readValue(region, new TypeReference<List<Integer>>() {
            });
        } catch (JsonProcessingException e) {
            log.error("解析region出错", e);
            throw new YunscException("解析region出错。。。");
        }

        return regionIds.contains(regionId);
    }

    /**
     * 获取积分抵扣金额
     *
     * @param discountRatio   积分抵扣比例 (设置1个积分可抵扣0.1元，则10积分可抵扣1元，100积分可抵扣10元)
     * @param maxOrderPrice   最大抵扣金额    =  （积分 * 10%）
     * @param orderTotalPrice 订单总金额
     * @param userPoints      用户积分
     * @return BigDecimal 积分抵扣金额
     */
    private static BigDecimal getPointsDeductionPrice(String discountRatio, String maxOrderPrice, BigDecimal
            orderTotalPrice, Integer userPoints) {
        // 设置积分抵扣价格
        BigDecimal pointsMoney = new BigDecimal(discountRatio).multiply(new BigDecimal(userPoints)).setScale(2, RoundingMode.HALF_UP);
        // 判断抵扣金额是否大于用户最大抵扣金额
        // 创建一个表示10%的BigDecimal对象，这里需要指定精度，因为0.1无法精确表示为二进制小数
        // 将值除以100
        BigDecimal value = new BigDecimal(maxOrderPrice);
        BigDecimal maxPriceRadio = value.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
        // 最大抵扣金额
        BigDecimal maxPointsMoney = orderTotalPrice.multiply(maxPriceRadio).setScale(2, RoundingMode.HALF_UP);
        if (pointsMoney.compareTo(maxPointsMoney) > 0) {
            return maxPointsMoney;
        } else {
            return pointsMoney;
        }

    }


    private List<YunscCartEntity> queryGoodsByCartIds(String cartIds) {
        if (cartIds == null || cartIds.trim().isEmpty()) {
            return Collections.emptyList();
        }

        try {
            List<Integer> ids = Arrays.stream(cartIds.split(","))
                    .map(String::trim) // 去除前后空白
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
            return cartService.listByIds(ids);
        } catch (NumberFormatException e) {
            // 这里可以根据需要处理错误，例如记录日志、抛出自定义异常等
            throw new NumberFormatException("输入字符串中包含非整数项: " + e.getMessage());
        }
    }

    private List<Integer> getCartIdsByCartId(String cartIds) {
        if (cartIds == null || cartIds.trim().isEmpty()) {
            return Collections.emptyList();
        }

        try {
            return Arrays.stream(cartIds.split(","))
                    .map(String::trim) // 去除前后空白
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
        } catch (NumberFormatException e) {
            // 这里可以根据需要处理错误，例如记录日志、抛出自定义异常等
            throw new NumberFormatException("输入字符串中包含非整数项: " + e.getMessage());
        }
    }


}
